package cn.keniykey.mc.landterritory.landflag;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;

import javax.annotation.Nullable;

import org.bukkit.plugin.InvalidDescriptionException;

public final class LandFlagLoader {
	private static ConcurrentHashMap<String,Class<?>> conmap_classes = new ConcurrentHashMap<>();
	private static CopyOnWriteArrayList<LandFlagClassLoader> cwlist_loaders = new CopyOnWriteArrayList<>();
	
	LandFlagLoader() {}
	
	@Nullable
	static Class<?> getFlagClass(final String name) {
		Class<?> find = conmap_classes.get(name);
		if (find != null) return find;
		for(final LandFlagClassLoader loader : cwlist_loaders) {
			try {
				find = loader.findClass(name, false);
			}catch(ClassNotFoundException ex) {
				continue;
			}
			if (find != null) break;
		}
		return find;
	}
	static void setClass(final String name, final Class<?> classs) {
		if (!conmap_classes.containsKey(name)) conmap_classes.put(name, classs);
	}
	public void close() {
		final Iterator<LandFlagClassLoader> it = cwlist_loaders.iterator();
		while(it.hasNext()) {
			final LandFlagClassLoader loader = it.next();
//			LandFlagManager.unloadFlag(loader.getFlag());
			try {
				loader.close();
			} catch (IOException ex) {
				ex.printStackTrace();
			}
		}
		return;
	}
	static void removeBufferClass(final Map<String,Class<?>> map) {
		final Iterator<Entry<String, Class<?>>> it = map.entrySet().iterator();
		while(it.hasNext()) conmap_classes.remove(it.next().getKey());
	}
	static void removeBufferClass(final String name) {
		conmap_classes.remove(name);
	}
	static void removeLandFlagClassLoader(LandFlagClassLoader loader) {
		final int index = cwlist_loaders.indexOf(loader);
		cwlist_loaders.remove(index);
	}
	public LandFlagDescription loadLandFlagDescription(final File file) throws InvalidDescriptionException{
		final JarFile jarfile;
		try {
			jarfile = new JarFile(file);
		} catch (IOException | SecurityException ex) {
			throw new InvalidDescriptionException(ex, "获取领地标记Description[LandFlagLoader]：无法将File转换为JarFile");
		}
		InputStream steam = null;
		try {
			final JarEntry en = jarfile.getJarEntry("landflag.yml");
			if (en == null || en.isDirectory()) {
				throw new InvalidDescriptionException("获取领地标记Description[LandFlagLoader]：Jar文件中缺少landflag.yml文件引导");
			}
			try {
				steam = jarfile.getInputStream(en);
			} catch (IOException ex) {
				throw new InvalidDescriptionException(ex, "获取领地标记Description[LandFlagLoader]：Jar文件中的landflag.yml无法获取数据");
			}
			return new LandFlagDescription(steam);
		}finally {
			if(steam != null) {
				try {
					steam.close();
				}catch(IOException ex) {}
			}
			try {
				jarfile.close();
			}catch(IOException ex) {}
		}
	}
	public LandFlagClassLoader loadLandFlag(final File file,final LandFlagDescription des) throws Exception{
		LandFlagClassLoader flagloader;
		try {
			flagloader = new LandFlagClassLoader(file, des, this.getClass().getClassLoader());
		} catch (IOException ex) {
			throw new Exception("无法成功加载LandFlag类[LandFlagLoader]：loadLandFlag", ex);
		}
		cwlist_loaders.add(flagloader);
		return flagloader;
	}
}